/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 *
 * $Id: JointGroupCtrlData.hpp,v 1.8 2009-05-13 07:18:17 amaula Exp $
 *
 * \file
 * \brief MaCI - JointGroupCtrl Data parser header
 * \author Matthieu Myrsky <matthieu.myrsky@tkk.fi>
 */
#ifndef _MACI_INTERFACE_JOINTGROUPCTRLDATA_HPP_
#define _MACI_INTERFACE_JOINTGROUPCTRLDATA_HPP_

#include "JointGroupCtrlTypes.hpp"
#include "timestamp.hpp"
#include "MaCIData.hpp"
#include <stdio.h>
#include <vector>
#include <math.h>
namespace gim {
  namespace binbag{class CBinBag;}
}

namespace MaCI {
  namespace JointGroupCtrl {

    typedef std::vector<const TJointSpeed *> TJointSpeedPtrArray;
    typedef std::vector<const TJointPosition *> TJointPositionPtrArray;
    typedef std::vector<const TJointForce *> TJointForcePtrArray;
    typedef std::vector<const TJointNumber *> TJointNumberPtrArray;

    /** JointGroupCtrl Data Decoder/Encoder.
     * This class implements 
     *
     */
    class CJointGroupCtrlData : public CMaCIData
    {
    public:
      /** Constructor.
       *
       */
      CJointGroupCtrlData(void);


      /** Destructor.
       *
       */
      ~CJointGroupCtrlData(void);
      

      /** Copy constructor for JointGroupCtrlData. 
       *
       * The copy constructor duplicates the input object to maximum
       * depth (All containers are duplicated too). After a copy is
       * constructed, no dependencies to original Data element exist.
       *
       * @param[in] aJointGroupCtrlData Reference to CJointGroupCtrlData 
       *            container to copy.
       */
      CJointGroupCtrlData(const CJointGroupCtrlData &aJointGroupCtrlData);

      

      /** Assignment operator for JointGroupCtrlData.
       *
       * The assignment operator duplicates the input object to
       * maximum depth (All containers are duplicated too). After a
       * copy is constructed, no dependencies to original Data element
       * exist.
       *
       * @param[in] aJointGroupCtrlData Reference to CJointGroupCtrlData 
       *            container to copy.
       */
      CJointGroupCtrlData &operator=(const CJointGroupCtrlData &aJointGroupCtrlData);



      ///////////////////////////////////////////////////
      // Derived from 'CMaCIData', see description there.
      bool DecodeFrom(gim::binbag::CBinBag *aBinBag = NULL);
      void Reset();
      void Print(const int level) const;
      ///////////////////////////////////////////////////

      /** Set Command element.
       *
       * Command elements must be accompanied by related dataelement
       * when required by commandtype. See the command enumerations
       * for a note about required datatype. (For example, 'SetSpeed'
       * command required a 'Speed' datatype after the command.
       * 
       * \see TCommand
       *
       * @param[in] aCmd        Command element to set.
       * @return                'true' if no such element previously
       *                        exists, and a valid binbag::CBinBag backend exists.
       */
      bool SetCommand(const TCommand &aCmd);

     
      /** Set Joint Speed element.
       * 
       * \see TJointSpeed
       *
       * @param[in] aSpeed      TJointSpeed element to set.
       * @return                'true' if no such element previously
       *                        exists, and a valid binbag::CBinBag backend exists.
       */
      bool SetSpeed(const TJointSpeed &aSpeed);


      /** Set Joint Position element.
       * 
       * \see TJointPosition
       *
       * @param[in] aPosition   TJointPosition element to set.
       * @return                'true' if no such element previously
       *                        exists, and a valid binbag::CBinBag backend exists.
       */
      bool SetPosition(const TJointPosition &aPosition);

      /** Set Joint Force element.
       * 
       * \see TJointForce
       *
       * @param[in] aForce      TJointForce element to set.
       * @return                'true' if no such element previously
       *                        exists, and a valid binbag::CBinBag backend exists.
       */
      bool SetForce(const TJointForce &aForce);

      /** Set Joint Information Header element.
       *
       * \see TJointInformationHeader
       * 
       * @param[in] aHeader     TJointInformationHeader element to set.
       * @return                'true' if no such element previously
       *                        exists, and a valid binbag::CBinBag backend exists.
       */
      bool SetJointInformationHeader(const TJointInformationHeader &aHeader);

      /** Set Joint Information payload  element.
       *
       * \see TJointInformation_Payload
       * 
       * @param[in] aInfo       TJointInformation_Payload element to set.
       * @return                'true' if no such element previously
       *                        exists, and a valid binbag::CBinBag backend exists.
       */
      bool SetJointInformation(const TJointInformation_Payload &aInfo);

      /** Set JointNumber payload  element.
       *
       * \see TJointNumber
       * 
       * @param[in] aNumber     TJointNumber element to set.
       * @return                'true' if no such element previously
       *                        exists, and a valid binbag::CBinBag backend exists.
       */
      bool SetJointNumber(const TJointNumber &aNumber);

      /** Set JointGroupStatus payload  element.
       *
       * \see TJointGroupStatus
       * 
       * @param[in] aStatus     TJointGroupStatus element to set.
       * @return                'true' if no such element previously
       *                        exists, and a valid binbag::CBinBag backend exists.
       */
      bool SetJointGroupStatus(const TJointGroupStatus &aStatus);
      
      /** Set JointGroupStatus payload  element.
       *
       * \see TEventTypes
       * 
       * @param[in] aEventTypes TEventTypes element to set.
       * @return                'true' if no such element previously
       *                        exists, and a valid binbag::CBinBag backend exists.
       */
      bool SetEventTypes(const TEventTypes &aEventTypes);

       /** Get constant pointer to TCommand element (if such exists).
       *
       * \see TCommand
       * 
       * @return                Constant pointer to command
       *                        element if such element exists
       *                        in the container. If the element 
       *                        doesn't exist, NULL is returned.
       */
      const TCommand *GetCommand(void) const;

      /** Get constant pointer to TJointSpeed element (if such exists). 
       *
       * \deprecated This function is no longer in use. Use GetJointSpeedPtrArray
       * function instead, because now adding multiple TJointSpeed elements is 
       * supported. If you use this function, you get only the first speed element
       *
       * \see TJointSpeed
       * 
       * @return                Constant pointer to speed
       *                        element if such element exists
       *                        in the container. If the element 
       *                        doesn't exist, NULL is returned.
       */
      const TJointSpeed *GetJointSpeed(void) const __attribute__((deprecated));
     
      /** Get reference to TJointSpeedPtrArray element (if such exists).
       *
       * \see TJointSpeed
       * \see TJointSpeedPtrArray
       * 
       * @return                Constant pointer to speed
       *                        element if such element exists
       *                        in the container. If the element 
       *                        doesn't exist, NULL is returned.
       */
      const TJointSpeedPtrArray &GetJointSpeedPtrArray(void) const;

      /** Get constant pointer to TJointPosition element (if such exists).
       *
       * \deprecated This function is no longer in use. Use GetJointPositionPtrArray
       * function instead, because now adding multiple TJointPosition elements is 
       * supported. If you use this function, you get only the first position element
       *
       * \see TJointPosition
       * 
       * @return                Constant pointer to speed
       *                        element if such element exists
       *                        in the container. If the element 
       *                        doesn't exist, NULL is returned.
       */
      const TJointPosition *GetJointPosition(void) const __attribute__((deprecated));

      /** Get reference to TJointPositionPtrArray element (if such exists).
       *
       * \see TJointPosition
       * \see TJointPositionPtrArray
       * 
       * @return                Constant pointer to position
       *                        element if such element exists
       *                        in the container. If the element 
       *                        doesn't exist, NULL is returned.
       */
      const TJointPositionPtrArray &GetJointPositionPtrArray(void) const;

      /** Get constant pointer to TJointForce element (if such exists).
       *
       * \deprecated This function is no longer in use. Use GetJointForcePtrArray
       * function instead, because now adding multiple TJointForce elements is 
       * supported. If you use this function, you get only the first force element
       *
       * \see TJointForce
       * 
       * @return                Constant pointer to force
       *                        element if such element exists
       *                        in the container. If the element 
       *                        doesn't exist, NULL is returned.
       */
      const TJointForce *GetJointForce(void) const __attribute__((deprecated));

      
      /** Get reference to TJointForcePtrArray element (if such exists).
       *
       * \see TJointForce
       * \see TJointForcePtrArray
       * 
       * @return                Constant pointer to force
       *                        element if such element exists
       *                        in the container. If the element 
       *                        doesn't exist, NULL is returned.
       */
      const TJointForcePtrArray &GetJointForcePtrArray(void) const;

      /** Get constant pointer to TJointInformationHeader element(if it exists).
       *
       * \see TJointInformationHeader
       * 
       * @return                TJointInformationHeader constant pointer if it exists.
       *                        If the element doesn't exist, NULL is returned.
       */
      const TJointInformationHeader *GetJointInformationHeader(void) const;

      /** Get constant pointer to TJointInformation_Payload element(if it exists).
       *
       * \see TJointInformation_Payload
       * 
       * @return                TJointInformation_Payload constant pointer if it exists.
       *                        If the element doesn't exist, NULL is returned.
       */
      const TJointInformation_Payload *GetJointInformation(const int aIndex) const;

      /** Get constant pointer to TJointNumber element(if it exists).
       *
       * \see TJointNumber
       * 
       * @return                TJointNumber constant pointer if it exists.
       *                        If the element doesn't exist, NULL is returned.
       */
      const TJointNumber *GetJointNumber() const;

      /** Get constant pointer to TJointGroupStatus element(if it exists).
       *
       * \see TJointGroupStatus
       * 
       * @return                TJointGroupStatus constant pointer if it exists.
       *                        If the element doesn't exist, NULL is returned.
       */
      const TJointGroupStatus *GetJointGroupStatus() const;

      const TEventTypes *GetEventTypes() const;

    private:
      bool iValid;

      const TCommand *iCommandPtr;
      TJointSpeedPtrArray iJointSpeedPtrArray;
      TJointPositionPtrArray iJointPositionPtrArray;
      TJointForcePtrArray iJointForcePtrArray;
      const TJointNumber *iJointNumberPtr;
      const TJointInformationHeader *iJointInformatioHeaderPtr;
      const TJointInformation_Payload *iJointInformation_PayloadPtr;
      const TEventTypes *iEventTypesPtr;
     
      const TJointGroupStatus *iJointGroupStatusPtr;

      int iJointInfoElementCount; ///< Number of jointInfo elements
    };
  }
}

#endif //_MACI_INTERFACE_JOINTGROUPCTRLDATA_HPP_
